package cn.tedu.project.oa.base.util;


import cn.tedu.project.oa.base.exception.TokenAuthException;
import cn.tedu.project.oa.sys.common.ResponseCodeConstants;
import cn.tedu.project.oa.sys.user.pojo.dto.LoginPara;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class TokenUtil {

    @Value("${token.secretKey}")
    private String secretKey;

    @Value("${token.expiresTime}")
    private long expiresTime;

    /**
     * 生成 JWT Token
     *
     * @param loginPara 包含用户名和验证码的对象
     * @return 生成的 JWT Token
     */
    public String getToken(LoginPara loginPara) {
        Date now = new Date();
        Date expiration = new Date(now.getTime() + expiresTime);  // 计算过期时间

        // 使用 HMAC256 算法生成 JWT Token
        String token = JWT.create()
                .withClaim("username", loginPara.getUsername())
                .withIssuedAt(now)  // 当前时间戳
                .withExpiresAt(expiration)  // 过期时间
                .sign(Algorithm.HMAC256(secretKey));

        log.debug("TokenUtil中生成的token: {}", token);
        return token;
    }

    /**
     * 解析 JWT Token
     *
     * @param token 要解析的 Token
     * @return 解析后的信息，以 Map 形式返回
     */
    public Map<String, Object> parseToken(String token) {
        Map<String, Object> map = new HashMap<>();

        DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(secretKey))
                .build()
                .verify(token);

        // 提取 Token 中的各个字段信息
        map.put("username", decodedJWT.getClaim("username").asString());
        map.put("issuedAt", decodedJWT.getIssuedAt());
        map.put("expiresAt", decodedJWT.getExpiresAt());

        log.debug("解析后的信息: {}", map);
        return map;
    }

    /**
     * 判断 Token 是否过期
     * @param token 要判断的 Token
     * @return 如果 Token 已过期，返回 true；否则返回 false
     */
    public boolean isExpired(String token) {
        try {
            DecodedJWT decodedJWT = JWT.require(Algorithm.HMAC256(secretKey)).build().verify(token);
            Date expiration = decodedJWT.getExpiresAt();
            return expiration.before(new Date());
        } catch (TokenExpiredException e) {
            log.debug("Token 已过期");
            return true;  // 直接返回 token 已过期
        } catch (Exception e) {
            log.error("Token 验证失败", e);
            throw new TokenAuthException(ResponseCodeConstants.TOKEN_INVALIDED, "Token 验证失败");
        }
    }


    /**
     * 验证 JWT 是否有效
     *
     * @param token JWT字符串
     * @return 如果JWT有效，返回 true；否则返回 false
     */
    public boolean validateToken(String token, String username) {
        Map<String, Object> map = parseToken(token);
        String tokenUsername = (String) map.get("username");

        // 校验 Token 中的用户名是否与传入的用户名一致，并且 Token
        return (tokenUsername != null && tokenUsername.equals(username));
    }
}
